/*
 * Copyright (c) $today.year-Now http://www.zxpnet.com All rights reserved.
 */

package com.zxp.common.core.security.authentication.handler;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zxp.common.api.R;
import com.zxp.common.core.security.properties.SecurityProperties;
import com.zxp.common.core.validatecode.ValidateCodeProperties;
import com.zxp.common.utils.WebUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.log.LogMessage;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 认证成功处理器
 * @author: shollin
 * @date: 2021/7/6/006 6:52
 */
//@Component
@Slf4j
@RequiredArgsConstructor
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    private  final ObjectMapper objectMapper;
    private final SecurityProperties securityProperties;
    private final ClientDetailsService clientDetailsService;
    private final AuthorizationServerTokenServices authorizationServerTokenServices;

    private BasicAuthenticationConverter authenticationConverter = new BasicAuthenticationConverter();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        String contentType = request.getContentType();
        log.info("验证成功！{} {}",contentType,authentication);
        

        String header = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StrUtil.isNotBlank(header)) {
            // 发放令牌
            // 第一步：从header里面解析出client_id 和client_secret,参考BasicAuthenticationFilter
            UsernamePasswordAuthenticationToken authRequest = authenticationConverter.convert(request);

            if (authRequest == null) {
                this.logger.trace("Did not process authentication request since failed to find username and password in Basic Authorization header");
                throw new UnapprovedClientAuthenticationException("client_id不存在");
            }
            String clientId = authRequest.getName();
            String clientSecret = (String) authRequest.getCredentials();
            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
            if(clientDetails==null){
                throw new UnapprovedClientAuthenticationException("client_id对应的匹配令牌不存在:"+clientId);
            }else if(!clientSecret.equals(clientDetails.getClientSecret())){
                throw new UnapprovedClientAuthenticationException("client_secret不匹配"+clientId);
            }

            // 第二步: 生成OAuth2Authentication，参考源码：TokenEndpoint、ResourceOwnerPasswordTokenGranter
            String grantType="custom";
            TokenRequest tokenRequest = new TokenRequest(MapUtil.empty(), clientId, clientDetails.getScope(),grantType);
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

            // 第三步：调用AuthorizationServerTokenServices创建令牌，参考源码： AbstractTokenGranter
            OAuth2AccessToken accessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
            WebUtil.renderJson(response, R.data(accessToken));
            return;
        }


        if (WebUtil.isAjaxRequest(request)) {
            WebUtil.renderJson(response,R.data(authentication));
        } else {
            // 存到session里，方便取值。
            request.getSession().setAttribute("authentication", authentication);
            // 支持跳转到自定义页面

            // 会帮我们跳转到上一次请求的页面上
            super.onAuthenticationSuccess(request, response, authentication);

        }
    }
}
